package com.chat.websocket.domain;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.ImmediateEventExecutor;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 崔超
 * 2022/2/12
 */
public class ChatInfoContainer {
    private static final Map<String, MemberInfo> userMap = new HashMap<>();
    private static final Map<String, ChannelGroup> roomChannelMap = new HashMap<>();

    static public boolean enterChatRoom(ChannelHandlerContext ctx, String roomName, String nickName) {
        boolean isNewRoom;
        ChannelGroup channels = roomChannelMap.get(roomName);
        if (channels == null) {
            channels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
            channels.add(ctx.channel());
            roomChannelMap.put(roomName, channels);
            isNewRoom = true;
        } else {
            channels.add(ctx.channel());
            isNewRoom = false;
        }

        MemberInfo info = new MemberInfo(roomName,nickName,new Random().nextInt(10));
        userMap.put(ctx.channel().id().asLongText(), info);
        return isNewRoom;
    }

    static public MemberInfo getMemberInfo(ChannelHandlerContext ctx) {
        MemberInfo info = userMap.get(ctx.channel().id().asLongText());
        assert info != null;
        return info;
    }


    static public void leaveChatRoom(ChannelHandlerContext ctx) {
        MemberInfo info = userMap.get(ctx.channel().id().asLongText());
        ChannelGroup channels = roomChannelMap.get(info.getRoomName());
        channels.remove(ctx.channel());

        if (channels.isEmpty()) {
            roomChannelMap.remove(info.getRoomName());
        }

        userMap.remove(ctx.channel().id().asLongText());
        ctx.close();
    }


    static public void sendMsgToChatRoom(ChannelHandlerContext ctx, String msg) {
        MemberInfo info = userMap.get(ctx.channel().id().asLongText());
        ChannelGroup channelGroup = roomChannelMap.get(info.getRoomName());
        TextWebSocketFrame frame = new TextWebSocketFrame(msg);

        channelGroup.writeAndFlush(frame.retain()).addListener(future -> {
            if (!future.isSuccess()) {
                future.cause().printStackTrace();
            }
        });
    }

    static public long getPersonCountInCurRoom(ChannelHandlerContext ctx) {
        MemberInfo info = userMap.get(ctx.channel().id().asLongText());
        ChannelGroup channels = roomChannelMap.get(info.getRoomName());
        return channels.size();
    }

    static public ChannelGroup getCurChannelGroup(ChannelHandlerContext ctx) {
        MemberInfo info = userMap.get(ctx.channel().id().asLongText());
        return roomChannelMap.get(info.getRoomName());
    }

    static public List<MemberInfo> getPersonsInRoom(String roomName) {
        Set<Map.Entry<String, MemberInfo>> entries = userMap.entrySet();
        return entries.stream()
                .filter(entry -> {
                    MemberInfo info = entry.getValue();
                    return info.getRoomName().equals(roomName);
                })
                .map(Map.Entry::getValue).collect(Collectors.toList());
    }

}
